package com.inspur.jzsxxzx.util;

import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.util.MultiValueMap;

import javax.annotation.PostConstruct;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.SSLContext;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.time.Instant;
import java.util.Base64;

/**
 * HTTPS API请求工具类
 * 用于请求特定的HTTPS接口并接收返回结果
 */
@Component
public class SjzdApiUtils {

    @Value("${api.base-url}")
    private String baseUrl;
    
    @Value("${api.rid}")
    private String rid;
    
    @Value("${api.client-secret}")
    private String clientSecret;
    
    private RestTemplate restTemplate;
    
    @PostConstruct
    @SuppressWarnings("null")
    public void init() {
        try {
            // 创建信任所有证书的策略
            TrustStrategy acceptingTrustStrategy = new TrustStrategy() {
                @Override
                public boolean isTrusted(X509Certificate[] certificate, String authType) {
                    return true;
                }
            };
            
            // 创建SSL上下文
            SSLContext sslContext = SSLContexts.custom()
                    .loadTrustMaterial(null, acceptingTrustStrategy)
                    .build();
            
            // 创建SSL连接套接字工厂
            SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(
                    sslContext, 
                    NoopHostnameVerifier.INSTANCE);
            
            // 创建HttpClient
            CloseableHttpClient httpClient = HttpClients.custom()
                    .setSSLSocketFactory(csf)
                    .build();
            
            // 创建RestTemplate
            HttpComponentsClientHttpRequestFactory requestFactory = 
                    new HttpComponentsClientHttpRequestFactory();
            requestFactory.setHttpClient(httpClient);
            
            restTemplate = new RestTemplate(requestFactory);
        } catch (Exception e) {
            throw new RuntimeException("初始化HTTPS客户端失败", e);
        }
    }
    
    /**
     * 生成API请求签名
     * 
     * @param sid 服务ID
     * @param timestamp 时间戳
     * @return sign
     */
    public String getSign(String sid, String timestamp) {
        String textToSign = sid + rid + timestamp;

        try {
            Mac sha256Hmac = Mac.getInstance("HmacSHA256");
            SecretKeySpec secretKey = new SecretKeySpec(clientSecret.getBytes(), "HmacSHA256");
            sha256Hmac.init(secretKey);
            byte[] hashBytes = sha256Hmac.doFinal(textToSign.getBytes());
            String sign = Base64.getEncoder().encodeToString(hashBytes);

            return sign;

        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            throw new RuntimeException("生成签名时出错", e);
        }
    }
    
    /**
     * 构建带认证信息的请求头
     * 
     * @param sid 服务ID
     * @return HttpHeaders 带认证信息的请求头
     */
    private HttpHeaders buildAuthHeaders(String sid) {
        String rtime = String.valueOf(Instant.now().toEpochMilli());
        String sign = getSign(sid, rtime);
        
        HttpHeaders headers = new HttpHeaders();
        headers.add("sjgxjhpt_rid", rid);
        headers.add("sjgxjhpt_sid", sid);
        headers.add("sjgxjhpt_rtime", rtime);
        headers.add("sjgxjhpt_sign", sign);
        headers.add("Content-Type", "application/json");
        
        return headers;
    }
    
    /**
     * 发送带认证信息的GET请求到指定的API路径
     * 
     * @param apiPath API路径（同时也是服务ID）
     * @param requestBody 可选的请求体（可以为null）
     * @param queryParams 可选的查询参数（可以为null）
     * @return ResponseEntity<String> 响应结果
     */
    @SuppressWarnings("null")
    public ResponseEntity<String> get(String apiPath, Object requestBody, MultiValueMap<String, String> queryParams) {
        String url = baseUrl + apiPath;
        HttpHeaders headers = buildAuthHeaders(apiPath);
        
        // 根据是否有请求体来构建HttpEntity
        HttpEntity<Object> entity;
        if (requestBody != null) {
            entity = new HttpEntity<>(requestBody, headers);
        } else {
            entity = new HttpEntity<>(headers);
        }
        
        // 根据是否有查询参数来调用exchange方法
        if (queryParams != null) {
            return restTemplate.exchange(url, HttpMethod.GET, entity, String.class, queryParams);
        } else {
            return restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
        }
    }
    
    /**
     * 发送带认证信息的POST请求到指定的API路径
     * 
     * @param apiPath API路径（同时也是服务ID）
     * @param requestBody 请求体
     * @return ResponseEntity<String> 响应结果
     */
    public ResponseEntity<String> post(String apiPath, Object requestBody) {
        String url = baseUrl + apiPath;
        HttpHeaders headers = buildAuthHeaders(apiPath);
        HttpEntity<Object> entity = 
                new HttpEntity<>(requestBody, headers);
        
        return restTemplate.postForEntity(url, entity, String.class);
    }
    
    /**
     * 发送带认证信息的PUT请求到指定的API路径
     * 
     * @param apiPath API路径（同时也是服务ID）
     * @param requestBody 请求体
     * @return ResponseEntity<String> 响应结果
     */
    public ResponseEntity<String> put(String apiPath, Object requestBody) {
        String url = baseUrl + apiPath;
        HttpHeaders headers = buildAuthHeaders(apiPath);
        HttpEntity<Object> entity = 
                new HttpEntity<>(requestBody, headers);
        
        return restTemplate.exchange(url, HttpMethod.PUT, entity, String.class);
    }
    
    /**
     * 发送带认证信息的DELETE请求到指定的API路径
     * 
     * @param apiPath API路径（同时也是服务ID）
     * @return ResponseEntity<String> 响应结果
     */
    @SuppressWarnings("null")
    public ResponseEntity<String> delete(String apiPath) {
        String url = baseUrl + apiPath;
        HttpHeaders headers = buildAuthHeaders(apiPath);
        HttpEntity<Object> entity = 
                new HttpEntity<>(headers);
        
        return restTemplate.exchange(url, HttpMethod.DELETE, entity, String.class);
    }
}